/*************************************************************************
  > File Name: src/pcduino.c
  > Author: yuarmy
  > Mail: yuarmy@126.com 
  > Created Time: Wed 06 Aug 2014 05:21:57 AM PDT
 ************************************************************************/

#include<stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <memory.h>
#include <time.h>
#include "pcduino.h"

#define GPIO_MODE_DIR "/sys/devices/virtual/misc/gpio/mode/"
#define GPIO_PIN_DIR "/sys/devices/virtual/misc/gpio/pin/"
#define MAX_GPIO_NUM 23
#define MAX_GPIO_MODE_NUM 8
#define GPIO0  0 
#define GPIO1  1 
#define IO_UART_FUNC  3
#define GPIO_IF_PREFIX "gpio"

int gpio_pin_fd[MAX_GPIO_NUM+1];
int gpio_mode_fd[MAX_GPIO_NUM+1];

static int write_to_file(int fd, char *str, int len)
{
  int ret = -1;

  lseek(fd, 0, SEEK_SET);
  ret = write(fd, str, len);
  if ( ret <= 0 )
  {
	fprintf(stderr, "write %d failed\n", fd);
	return -1;
  }
  return ret;
}

static int32_t hw_pinMode(uint8_t pin, uint8_t mode)
{
  int fd;
  char buf[4];
  int ret = -1;

  if ( (pin >= 0 && pin <=  MAX_GPIO_NUM) && (mode <= MAX_GPIO_MODE_NUM) )
  {
	memset((void *)buf, 0, sizeof(buf));
	sprintf(buf, "%d", mode);
	ret = write_to_file(gpio_mode_fd[pin], buf, sizeof(buf));
	if ( ret <= 0 )
	{
	  fprintf(stderr, "write gpio %d mode failed\n", pin);
	  return -1;
	}
  }
  else
  {
	fprintf(stderr, "%s ERROR: invalid pin or mode, pin=%d, mode=%d\n",
		__FUNCTION__, pin, mode);
	return -1;
  }
  return 0;
}

static int32_t InitGPIO() {
  int i;
  char path[1024];
  for( i = 0; i<= MAX_GPIO_NUM; ++i)
  {
	memset(path, 0, sizeof(path));
	sprintf(path, "%s%s%d", GPIO_PIN_DIR, GPIO_IF_PREFIX, i);
	gpio_pin_fd[i] = open(path, O_RDWR);
	if ( gpio_pin_fd[i] < 0 )
	{
	  fprintf(stderr, "open %s failed\n", path);
	  return -1;
	}

	memset(path, 0, sizeof(path));
	sprintf(path, "%s%s%d", GPIO_MODE_DIR, GPIO_IF_PREFIX, i);
	gpio_mode_fd[i] = open(path, O_RDWR);
	if ( gpio_mode_fd[i] < 0 )
	{
	  fprintf(stderr, "open %s failed\n", path);
	  return -1;
	} 
  }

  return 0;
}

int32_t InitUart2() {
  InitGPIO();
  hw_pinMode(GPIO0, IO_UART_FUNC);
  hw_pinMode(GPIO1, IO_UART_FUNC);
}
